package service

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"goserver/internal/model"
	"goserver/internal/utils"
	"log"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/gorilla/websocket"
)

var (
	onlineCache   sync.Map
	lastCheckTime sync.Map
)

type DeviceManager struct {
	connections    sync.Map
	mu             sync.RWMutex
	deviceInfo     sync.Map
	unreadMessages sync.Map
}

type DeviceService struct {
	db *sql.DB
}

type RobotConfig struct {
	RobotID       string    `json:"robot_id"`
	QAType        int       `json:"qa_type"`
	CallbackURL   string    `json:"callback_url"`
	ReplyAll      int       `json:"reply_all"`
	RobotKeyCheck int       `json:"robot_key_check"`
	EncryptType   int       `json:"encrypt_type"`
	Status        int       `json:"status"`
	ExpireTime    time.Time `json:"expire_time"`
}

// GetConnection 获取设备的 WebSocket 连接
func (m *DeviceManager) GetConnection(deviceId string) (*websocket.Conn, bool) {
	if conn, ok := m.connections.Load(deviceId); ok {
		if ws, ok := conn.(*websocket.Conn); ok {
			return ws, true
		}
	}
	return nil, false
}

type DeviceInfo struct {
	// API 响应字段
	RobotId             string `json:"robotId"`
	Name                string `json:"name"`
	Corporation         string `json:"corporation"`         // 企业名称
	SumInfo             string `json:"sumInfo"`             // 摘要信息
	OpenCallback        int    `json:"openCallback"`        // 是否开启回调
	EncryptType         int    `json:"encryptType"`         // 加密类型
	CreateTime          int64  `json:"createTime"`          // 创建时间
	QaUrl               string `json:"callbackUrl"`         // 回调地址
	EnableAdd           bool   `json:"enableAdd"`           // 是否允许加
	ReplyAll            int    `json:"replyAll"`            // 回复策略 1:开启 -1:关闭
	AppidId             string `json:"appidId"`             // 应用ID
	Token               string `json:"token"`               // 访问令牌
	EnoodingAeskey      string `json:"enoodingAeskey"`      // AES密钥
	Signature           string `json:"signature"`           // 签名
	SignatureTime       int64  `json:"signatureTime"`       // 签名时间
	RobotKeyCheck       int    `json:"robotKeyCheck"`       // 机器人密钥检查
	CallBackRequestType int    `json:"callBackRequestType"` // 回调请求类型
	UserId              int64  `json:"userId"`              // 用户ID
	RobotType           int    `json:"robotType"`           // 机器人类型
	FirstLogin          string `json:"firstLogin"`          // 首次登录时间
	AuthExpir           string `json:"authExpir"`           // 授权过期时间

	// 服务器配置字段
	ServerHost string `json:"-"` // 服务器地址
	ServerPort string `json:"-"` // 服务器端口
	ServerPath string `json:"-"` // 服务器路径
	ServerType int    `json:"-"` // 服务器类型

	// 设备信息字段
	Avatar      string `json:"-"` // 头像
	AppVersion  string `json:"-"` // APP版本
	WorkVersion string `json:"-"` // 企微版本
	DeviceInfo  string `json:"-"` // 设备信息
	AppName     string `json:"-"` // APP名称
	LoginType   int    `json:"-"` // 登录类型
	VisitorId   string `json:"-"` // 访客ID
	VisitorName string `json:"-"` // 访客名称

	// 企业微信相关字段
	WeworkCorpName string `json:"-"` // 企业名称
	WeworkCorpId   string `json:"-"` // 企业ID
	WeworkAgentId  string `json:"-"` // 应用ID
	WeworkSchema   string `json:"-"` // Schema
	WeworkMP       string `json:"-"` // 小程序ID

	// 功能开关字段
	GroupStrict        bool `json:"-"` // 群名称严格匹配
	FriendRemarkStrict bool `json:"-"` // 好友备注严格匹配
	PushImage          bool `json:"-"` // 是否推送图片
	AutoPublishComment bool `json:"-"` // 自动发布评论
	GroupQrCode        bool `json:"-"` // 群二维码
	EnableMediaProject bool `json:"-"` // 启用媒体投影
	EnableSdkShare     bool `json:"-"` // 启用SDK分享
	CustomLink         bool `json:"-"` // 自定义链接
	CustomMP           bool `json:"-"` // 自定义小程序
	OldDevice          bool `json:"-"` // 旧设备模式

	// 权限相关字段
	CanDrawOverlays           bool            `json:"-"` // 悬浮窗限
	CanBackgroundStart        bool            `json:"-"` // 后台启动权限
	NotShowFloatGuide         bool            `json:"-"` // 不显示悬浮窗引导
	Permissions               map[string]bool `json:"-"` // 权限列表
	AccessibilityEnabled      bool            `json:"-"` // 无障碍服务开启状态
	NotShowAccessibilityGuide bool            `json:"-"` // 不显示无障碍引导

	// 状态相关字段
	DeviceRooted bool      `json:"-"` // 设备是否已root
	DeviceHooked bool      `json:"-"` // 设备是否被hook
	RiskLevel    int       `json:"-"` // 风险等级
	LastSeen     time.Time `json:"-"` // 最后在线时间
	UpdateTime   int64     `json:"-"` // 更新时间
	Online       bool      `json:"-"` // 在线状态

	// 消息相关字段
	ReplyStrategy         int     `json:"-"` // 回复策略
	AutoReply             int     `json:"-"` // 自动回复
	AutoPassFriendRequest bool    `json:"-"` // 自动通过好友请求
	FullGroupName         bool    `json:"-"` // 完整群名
	DuplicationFilter     bool    `json:"-"` // 重复过滤
	UnreadCount           int     `json:"-"` // 未读消息数
	UnreadMessages        []gin.H `json:"-"` // 未读消息列表
}

type DeviceConfig struct {
	RobotId     string `json:"robotId"`
	ServerHost  string `json:"serverHost"`
	ServerPort  string `json:"serverPort"`
	ServerPath  string `json:"serverPath"`
	ServerType  int    `json:"serverType"`
	Status      int    `json:"status"`      // 设备状态
	AccessToken string `json:"accessToken"` // 访问令牌
}

const (
	DefaultHost = "wss://rag.aihaoan.com"
	DefaultQaUrl = "https://api.chengmingyi.cn/api/hamibot/notify" // 默认回调地址

	// 回复策略
	ReplyStrategyNone    = 0 // 只读消息不回调
	ReplyStrategyPrivate = 1 // 仅私聊和私聊@机器人回调
	ReplyStrategyAll     = 2 // 私聊群聊全部回调

	// 设备状态
	DeviceStatusOffline = 0 // 离线
	DeviceStatusOnline  = 1 // 在线
	DeviceStatusBusy    = 2 // 忙碌

	// 加密类型
	EncryptTypeNone = 0 // 不加密
	EncryptTypeAES  = 1 // AES加密

	// 回调开关
	CallbackDisabled = 0 // 关闭回调
	CallbackEnabled  = 1 // 开启回调

	// 自动回复
	AutoReplyDisabled = 0 // 关闭自动回复
	AutoReplyEnabled  = 1 // 开启自动回复

	// 风险等级
	RiskLevelNormal = 0 // 正常
	RiskLevelRisky  = 1 // 有风险

	// 服务器类型
	ServerTypeWS   = 1 // WebSocket
	ServerTypeHTTP = 2 // HTTP

	// 回调请求类型
	CallbackTypeNormal = 1 // 普通回调
	CallbackTypeAsync  = 2 // 异步回调

	// 登录类型
	LoginTypeVisitor = 0 // 游客登录
	LoginTypeNormal  = 1 // 正式登录
)

func NewDeviceManager() *DeviceManager {
	return &DeviceManager{}
}

func init() {
	// 设置时区为北京时间
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		log.Printf("Failed to load timezone: %v", err)
		return
	}
	time.Local = loc
}

func (m *DeviceManager) AddDevice(deviceId string, conn *websocket.Conn) {
	m.mu.Lock()
	defer m.mu.Unlock()

	log.Printf("[AddDevice] Start adding device %s to manager", deviceId)

	// 先关闭旧连接
	if oldConn, ok := m.connections.Load(deviceId); ok {
		if ws, ok := oldConn.(*websocket.Conn); ok {
			ws.SetWriteDeadline(time.Now().Add(time.Second))
			ws.WriteControl(websocket.CloseMessage,
				websocket.FormatCloseMessage(websocket.CloseNormalClosure, "new connection"),
				time.Now().Add(time.Second))
			time.Sleep(time.Millisecond * 100)
			ws.Close()
		}
	}

	// 存储新连接
	m.connections.Store(deviceId, conn)
	onlineCache.Store(deviceId, true)
	lastCheckTime.Store(deviceId, time.Now())
	log.Printf("[AddDevice] Stored new connection for %s", deviceId)

	// 设置连接参数
	conn.SetReadLimit(1024 * 1024) // 1MB
	conn.SetReadDeadline(time.Now().Add(time.Minute * 5))
	conn.SetWriteDeadline(time.Now().Add(time.Second * 10))

	// 设置关闭处理器
	conn.SetCloseHandler(func(code int, text string) error {
		log.Printf("[AddDevice] Connection closed for %s: %d %s", deviceId, code, text)
		m.RemoveDevice(deviceId)
		return nil
	})

	// 设置 ping handler
	conn.SetPingHandler(func(appData string) error {
		log.Printf("[AddDevice] Received ping from %s", deviceId)
		onlineCache.Store(deviceId, true)
		lastCheckTime.Store(deviceId, time.Now())
		conn.SetReadDeadline(time.Now().Add(time.Minute * 5))
		return nil
	})

	// 设置 pong handler
	conn.SetPongHandler(func(appData string) error {
		log.Printf("[AddDevice] Received pong from %s", deviceId)
		onlineCache.Store(deviceId, true)
		lastCheckTime.Store(deviceId, time.Now())
		return nil
	})

	// 启动心跳检查
	go m.startHeartbeat(deviceId, conn)

	// 设置默认值
	defaultValues := map[string]bool{
		"PushImage":             true,
		"GroupQrCode":           true,
		"AutoPassFriendRequest": true,
		"FullGroupName":         true,
		"DuplicationFilter":     true,
	}

	// 获取或创建设备信息
	var deviceInfo *DeviceInfo
	if info, ok := m.deviceInfo.Load(deviceId); ok {
		deviceInfo = info.(*DeviceInfo)
		deviceInfo.Online = true
		deviceInfo.LastSeen = time.Now()
		deviceInfo.UpdateTime = time.Now().UnixMilli()
		// 更新默认值
		deviceInfo.PushImage = defaultValues["PushImage"]
		deviceInfo.GroupQrCode = defaultValues["GroupQrCode"]
		deviceInfo.AutoPassFriendRequest = defaultValues["AutoPassFriendRequest"]
		deviceInfo.FullGroupName = defaultValues["FullGroupName"]
		deviceInfo.DuplicationFilter = defaultValues["DuplicationFilter"]
	} else {
		deviceInfo = &DeviceInfo{
			RobotId:               deviceId,
			ServerHost:            utils.WsUrlToHttpUrl(DefaultHost),
			ServerPort:            "443",
			ServerPath:            "/webserver/wework",
			ServerType:            ServerTypeWS,
			Name:                  "小铭",
			Corporation:           "诚铭艺",
			SumInfo:               "诚铭艺-小铭-小铭-添加工作签名…",
			OpenCallback:          CallbackEnabled,
			EncryptType:           EncryptTypeNone,
			CreateTime:            time.Now().UnixMilli(),
			QaUrl:                 DefaultQaUrl,
			EnableAdd:             true,
			ReplyAll:              1,
			AppidId:               "TAcaoOnsTJUttAi",
			Token:                 uuid.New().String(),
			EnoodingAeskey:        utils.GenerateAESKey(),
			SignatureTime:         time.Now().UnixMilli(),
			RobotKeyCheck:         RiskLevelNormal,
			CallBackRequestType:   CallbackTypeAsync,
			UserId:                time.Now().UnixNano(),
			RobotType:             RiskLevelNormal,
			FirstLogin:            time.Now().In(time.Local).Format("2006-01-02T15:04:05"),
			AuthExpir:             time.Now().In(time.Local).AddDate(1, 0, 0).Format("2006-01-02T15:04:05"),
			AppVersion:            "3.6.2.2",
			WorkVersion:           "4.1.31",
			DeviceInfo:            "Android Device",
			AppName:               "WT Pro",
			LoginType:             LoginTypeVisitor,
			VisitorId:             uuid.New().String(),
			VisitorName:           "游客" + time.Now().Format("20060102150405"),
			AutoReply:             AutoReplyEnabled,
			AutoPassFriendRequest: true,
			FullGroupName:         true,
			DuplicationFilter:     true,
			ReplyStrategy:         ReplyStrategyAll,
			Online:                true,
			LastSeen:              time.Now(),
			UpdateTime:            time.Now().UnixMilli(),
			WeworkCorpName:        "诚铭艺",
		}
	}

	// 保存设备信息
	m.deviceInfo.Store(deviceId, deviceInfo)
	log.Printf("[AddDevice] Device info saved: %+v", deviceInfo)
}

func (m *DeviceManager) RemoveDevice(deviceId string) {
	m.mu.Lock()
	defer m.mu.Unlock()

	log.Printf("[RemoveDevice] Removing device %s", deviceId)

	if conn, ok := m.connections.Load(deviceId); ok {
		if ws, ok := conn.(*websocket.Conn); ok {
			// 设置关闭超时
			ws.SetWriteDeadline(time.Now().Add(time.Second))
			// 发送关闭消息
			ws.WriteMessage(websocket.CloseMessage,
				websocket.FormatCloseMessage(websocket.CloseNormalClosure, "device removed"))
			ws.Close()
		}
	}

	// 清理连接和缓存
	m.connections.Delete(deviceId)
	onlineCache.Delete(deviceId)
	lastCheckTime.Delete(deviceId)

	// 更新设备信息
	if info, ok := m.deviceInfo.Load(deviceId); ok {
		deviceInfo := info.(*DeviceInfo)
		deviceInfo.Online = false
		deviceInfo.LastSeen = time.Now()
		deviceInfo.UpdateTime = time.Now().UnixMilli()
		m.deviceInfo.Store(deviceId, deviceInfo)
		log.Printf("[RemoveDevice] Updated device info: online=%v, lastSeen=%v",
			deviceInfo.Online, deviceInfo.LastSeen)
	}

	// 清理未读消息
	m.unreadMessages.Delete(deviceId)
}

func (m *DeviceManager) SendTextMessage(deviceId, roomId, text string) error {
	cmd := model.Command{
		Type: "sendTextMessage",
		Data: model.TextMessageData{
			RoomId: roomId,
			Text:   text,
		},
		MessageId: uuid.New().String(),
	}
	return m.sendCommand(deviceId, cmd)
}

func (m *DeviceManager) sendCommand(deviceId string, cmd model.Command) error {
	if conn, ok := m.connections.Load(deviceId); ok {
		if ws, ok := conn.(*websocket.Conn); ok {
			return ws.WriteJSON(cmd)
		}
	}
	return errors.New("device not connected")
}

func (m *DeviceManager) IsDeviceOnline(deviceId string) bool {
	m.mu.RLock()
	defer m.mu.RUnlock()

	log.Printf("[IsDeviceOnline] Checking online status for %s", deviceId)

	// 先检查缓存
	if lastCheck, ok := lastCheckTime.Load(deviceId); ok {
		if time.Since(lastCheck.(time.Time)) < time.Second*3 {
			if online, ok := onlineCache.Load(deviceId); ok {
				log.Printf("[IsDeviceOnline] Using cached status: %v", online.(bool))
				return online.(bool)
			}
		}
	}

	// 检查连接
	if conn, ok := m.connections.Load(deviceId); ok {
		if ws, ok := conn.(*websocket.Conn); ok {
			// 发送 ping 检查连接
			err := ws.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(time.Second))
			online := err == nil

			lastCheckTime.Store(deviceId, time.Now())
			onlineCache.Store(deviceId, online)

			if !online {
				// 如果���接已断开，异步移除设备
				go m.RemoveDevice(deviceId)
			}

			return online
		}
		// 移除无效连接
		m.connections.Delete(deviceId)
	}

	lastCheckTime.Store(deviceId, time.Now())
	onlineCache.Store(deviceId, false)
	return false
}

// DeviceError 设备错误
type DeviceError struct {
	Code     int    `json:"code"`
	Message  string `json:"message"`
	DeviceId string `json:"deviceId"`
}

func (e *DeviceError) Error() string {
	return fmt.Sprintf("device error: %s (code: %d, device: %s)", e.Message, e.Code, e.DeviceId)
}

// NewDeviceError 建设备错误
func NewDeviceError(code int, message string, deviceId string) *DeviceError {
	return &DeviceError{
		Code:     code,
		Message:  message,
		DeviceId: deviceId,
	}
}

func (m *DeviceManager) SendCommand(deviceId string, message interface{}) error {
	m.mu.RLock()
	defer m.mu.RUnlock()

	log.Printf("[SendCommand] Attempting to send command to device %s", deviceId)

	if conn, ok := m.connections.Load(deviceId); ok {
		log.Printf("[SendCommand] Found connection for device %s", deviceId)
		if ws, ok := conn.(*websocket.Conn); ok {
			log.Printf("[SendCommand] Preparing to send command: %+v", message)

			// 先检查连接状态
			pingErr := ws.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(time.Second*3))
			if pingErr != nil {
				log.Printf("[SendCommand] Connection check failed for device %s: %v", deviceId, pingErr)
				// 移除断开的连接
				m.RemoveDevice(deviceId)
				return NewDeviceError(4001, "connection check failed", deviceId)
			}

			// 设置超时
			ws.SetWriteDeadline(time.Now().Add(time.Second * 10))

			// 发送消息
			err := ws.WriteJSON(message)
			if err != nil {
				log.Printf("[SendCommand] Failed to write message to device %s: %v", deviceId, err)
				// 移除断开的连接
				m.RemoveDevice(deviceId)
				return fmt.Errorf("failed to send message to device %s: %v", deviceId, err)
			}

			log.Printf("[SendCommand] Command sent successfully to device %s", deviceId)
			return nil
		}
		log.Printf("[SendCommand] Connection for device %s is not a websocket connection", deviceId)
		return NewDeviceError(4002, "invalid connection type", deviceId)
	}
	log.Printf("[SendCommand] Device %s not found in connections", deviceId)
	return NewDeviceError(4003, "device not connected", deviceId)
}

func (m *DeviceManager) SaveConfig(deviceInfo *DeviceInfo) error {
	if deviceInfo == nil {
		return errors.New("device info is nil")
	}

	m.mu.Lock()
	defer m.mu.Unlock()

	deviceInfo.UpdateTime = time.Now().UnixMilli()
	m.deviceInfo.Store(deviceInfo.RobotId, deviceInfo)

	log.Printf("[SaveConfig] Saved config for device %s: %+v", deviceInfo.RobotId, deviceInfo)
	return nil
}

func (m *DeviceManager) GetDeviceInfo(robotId string) (*DeviceInfo, bool) {
	m.mu.RLock()
	if info, ok := m.deviceInfo.Load(robotId); ok {
		deviceInfo := info.(*DeviceInfo)
		m.mu.RUnlock()
		
		// 更新状态（不需要锁）
		deviceInfo.Online = m.IsDeviceOnline(robotId)
		deviceInfo.LastSeen = time.Now()
		deviceInfo.UpdateTime = time.Now().UnixMilli()
		deviceInfo.UnreadMessages = m.GetAndClearUnreadMessages(robotId)
		deviceInfo.UnreadCount = len(deviceInfo.UnreadMessages)
		
		// 保存更新（使用写锁）
		m.mu.Lock()
		m.deviceInfo.Store(robotId, deviceInfo)
		m.mu.Unlock()
		
		return deviceInfo, true
	}
	m.mu.RUnlock()

	// 创建新配置（使用写锁）
	m.mu.Lock()
	defer m.mu.Unlock()

	deviceInfo := &DeviceInfo{
		RobotId:               robotId,
		ServerHost:            utils.WsUrlToHttpUrl(DefaultHost),
		ServerPort:            "443",
		ServerPath:            "/webserver/wework",
		ServerType:            ServerTypeWS,
		Name:                  "小铭",
		Corporation:           "诚铭艺",
		SumInfo:               "诚铭艺-小铭-小铭-添加工作签名…",
		OpenCallback:          CallbackEnabled,
		EncryptType:           EncryptTypeNone,
		CreateTime:            time.Now().UnixMilli(),
		QaUrl:                 DefaultQaUrl,
		EnableAdd:             true,
		ReplyAll:              1,
		AppidId:               "TAcaoOnsTJUttAi",
		Token:                 uuid.New().String(),
		EnoodingAeskey:        utils.GenerateAESKey(),
		SignatureTime:         time.Now().UnixMilli(),
		RobotKeyCheck:         RiskLevelNormal,
		CallBackRequestType:   CallbackTypeAsync,
		UserId:                time.Now().UnixNano(),
		RobotType:             RiskLevelNormal,
		FirstLogin:            time.Now().In(time.Local).Format("2006-01-02T15:04:05"),
		AuthExpir:             time.Now().In(time.Local).AddDate(1, 0, 0).Format("2006-01-02T15:04:05"),
		AppVersion:            "3.6.2.2",
		WorkVersion:           "4.1.31",
		DeviceInfo:            "Android Device",
		AppName:               "WT Pro",
		LoginType:             LoginTypeVisitor,
		VisitorId:             uuid.New().String(),
		VisitorName:           "游客" + time.Now().Format("20060102150405"),
		AutoReply:             AutoReplyEnabled,
		AutoPassFriendRequest: true,
		FullGroupName:         true,
		DuplicationFilter:     true,
		ReplyStrategy:         ReplyStrategyAll,
		Online:                true,
		LastSeen:              time.Now(),
		UpdateTime:            time.Now().UnixMilli(),
		WeworkCorpName:        "诚铭艺",
	}
	m.deviceInfo.Store(robotId, deviceInfo)
	return deviceInfo, true
}

func (m *DeviceManager) GetDeviceConfig(robotId string) (*DeviceConfig, error) {
	deviceInfo, exists := m.GetDeviceInfo(robotId)
	if !exists {
		return nil, fmt.Errorf("device %s not found", robotId)
	}

	config := &DeviceConfig{
		RobotId:     deviceInfo.RobotId,
		ServerHost:  deviceInfo.ServerHost,
		ServerPort:  deviceInfo.ServerPort,
		ServerPath:  deviceInfo.ServerPath,
		ServerType:  deviceInfo.ServerType,
		Status:      map[bool]int{true: DeviceStatusOnline, false: DeviceStatusOffline}[deviceInfo.Online],
		AccessToken: deviceInfo.Token,
	}
	return config, nil
}

func (m *DeviceManager) GetLastSeen(robotId string) time.Time {
	if info, ok := m.deviceInfo.Load(robotId); ok {
		return info.(*DeviceInfo).LastSeen
	}
	return time.Time{}
}

func (m *DeviceManager) UpdateDeviceRisk(robotId string, rooted bool, hooked bool) error {
	deviceInfo, exists := m.GetDeviceInfo(robotId)
	if !exists {
		return errors.New("device not found")
	}

	deviceInfo.DeviceRooted = rooted
	deviceInfo.DeviceHooked = hooked
	deviceInfo.RiskLevel = map[bool]int{true: 1, false: 0}[rooted || hooked]

	return m.SaveConfig(deviceInfo)
}

func (m *DeviceManager) UpdatePermissions(robotId string, permissions map[string]bool) error {
	deviceInfo, exists := m.GetDeviceInfo(robotId)
	if !exists {
		return errors.New("device not found")
	}

	deviceInfo.CanDrawOverlays = permissions["canDrawOverlays"]
	deviceInfo.CanBackgroundStart = permissions["canBackgroundStart"]
	deviceInfo.NotShowFloatGuide = permissions["notShowFloatGuide"]

	if deviceInfo.Permissions == nil {
		deviceInfo.Permissions = make(map[string]bool)
	}
	for k, v := range permissions {
		deviceInfo.Permissions[k] = v
	}

	return m.SaveConfig(deviceInfo)
}

func (m *DeviceManager) UpdateAccessibilityStatus(robotId string, enabled bool, notShow bool) error {
	deviceInfo, exists := m.GetDeviceInfo(robotId)
	if !exists {
		return errors.New("device not found")
	}

	deviceInfo.AccessibilityEnabled = enabled
	deviceInfo.NotShowAccessibilityGuide = notShow

	return m.SaveConfig(deviceInfo)
}

func (m *DeviceManager) GetDeviceInfoRaw(robotId string) (*DeviceInfo, bool) {
	if info, ok := m.deviceInfo.Load(robotId); ok {
		return info.(*DeviceInfo), true
	}
	return nil, false
}

func (m *DeviceManager) AddUnreadMessage(robotId string, message gin.H) {
	m.mu.Lock()
	defer m.mu.Unlock()

	var messages []gin.H
	if existingMsgs, ok := m.unreadMessages.Load(robotId); ok {
		messages = existingMsgs.([]gin.H)
	}
	messages = append(messages, message)
	m.unreadMessages.Store(robotId, messages)
}

func (m *DeviceManager) GetAndClearUnreadMessages(robotId string) []gin.H {
	m.mu.Lock()
	defer m.mu.Unlock()

	if messages, ok := m.unreadMessages.Load(robotId); ok {
		m.unreadMessages.Delete(robotId)
		if msgList, ok := messages.([]gin.H); ok {
			return msgList
		}
	}
	return []gin.H{}
}

// VerifyDeviceStorage 验证设备信息是否正确存储
func (m *DeviceManager) VerifyDeviceStorage(robotId string) bool {
	m.mu.RLock()
	defer m.mu.RUnlock()

	// 检查连接
	if _, ok := m.connections.Load(robotId); !ok {
		log.Printf("[Verify] No connection found for %s", robotId)
		return false
	}

	// 检查设备信息
	if info, ok := m.deviceInfo.Load(robotId); !ok {
		log.Printf("[Verify] No device info found for %s", robotId)
		return false
	} else {
		deviceInfo := info.(*DeviceInfo)
		log.Printf("[Verify] Found device info for %s: %+v", robotId, deviceInfo)
		return true
	}
}

// GetOnlineDevices 获取所有在线设备
func (m *DeviceManager) GetOnlineDevices() []string {
	var devices []string
	m.connections.Range(func(key, value interface{}) bool {
		deviceId := key.(string)
		devices = append(devices, deviceId)
		return true
	})
	return devices
}

// GetDeviceCount 取设备总数和在线数
func (m *DeviceManager) GetDeviceCount() (total int, online int) {
	m.deviceInfo.Range(func(key, value interface{}) bool {
		total++
		deviceId := key.(string)
		if _, ok := m.connections.Load(deviceId); ok {
			online++
		}
		return true
	})
	return total, online
}

// GetDeviceStatus 获取设备状态
func (m *DeviceManager) GetDeviceStatus(robotId string) (online bool, lastSeen time.Time) {
	if info, ok := m.deviceInfo.Load(robotId); ok {
		deviceInfo := info.(*DeviceInfo)
		return deviceInfo.Online, deviceInfo.LastSeen
	}
	return false, time.Time{}
}

// GetDeviceStats 获取设备统计信息
func (m *DeviceManager) GetDeviceStats() map[string]interface{} {
	total, online := m.GetDeviceCount()
	return map[string]interface{}{
		"total":   total,
		"online":  online,
		"offline": total - online,
		"devices": m.GetOnlineDevices(),
	}
}

// BroadcastToOnlineDevices 向所有在线设备广播消息
func (m *DeviceManager) BroadcastToOnlineDevices(message interface{}) map[string]error {
	errors := make(map[string]error)
	devices := m.GetOnlineDevices()
	for _, deviceId := range devices {
		if err := m.SendCommand(deviceId, message); err != nil {
			errors[deviceId] = err
		}
	}
	return errors
}

// StartMonitor 启动设备连接监控
func (m *DeviceManager) StartMonitor() {
	go func() {
		ticker := time.NewTicker(time.Second * 30)
		defer ticker.Stop()

		for range ticker.C {
			m.mu.RLock()
			devices := m.GetOnlineDevices()
			m.mu.RUnlock()

			for _, deviceId := range devices {
				if !m.IsDeviceOnline(deviceId) {
					log.Printf("[Monitor] Device %s is offline, removing", deviceId)
					m.RemoveDevice(deviceId)
				}
			}
		}
	}()
}

// SendCommandWithRetry 发送命令自动重试
func (m *DeviceManager) SendCommandWithRetry(deviceId string, message interface{}, maxRetries int) error {
	var lastErr error
	for i := 0; i < maxRetries; i++ {
		if err := m.SendCommand(deviceId, message); err != nil {
			lastErr = err
			log.Printf("[SendCommand] Retry %d/%d failed: %v", i+1, maxRetries, err)
			time.Sleep(time.Second * time.Duration(i+1))
			continue
		}
		return nil
	}
	return fmt.Errorf("failed after %d retries: %v", maxRetries, lastErr)
}

// DeviceStatus 设备状态常量
type DeviceStatus int

const (
	StatusOffline DeviceStatus = iota // 离线
	StatusOnline                      // 在线
	StatusBusy                        // 忙碌
	StatusError                       // 错误
)

func (s DeviceStatus) String() string {
	switch s {
	case StatusOffline:
		return "offline"
	case StatusOnline:
		return "online"
	case StatusBusy:
		return "busy"
	case StatusError:
		return "error"
	default:
		return "unknown"
	}
}

// IsValid 检查状态是否有效
func (s DeviceStatus) IsValid() bool {
	return s >= StatusOffline && s <= StatusError
}

// startHeartbeat 启动心跳检查
func (m *DeviceManager) startHeartbeat(deviceId string, conn *websocket.Conn) {
	ticker := time.NewTicker(time.Second * 30)
	defer ticker.Stop()

	failCount := 0
	const maxFails = 3
	const pingTimeout = time.Second * 3

	for range ticker.C {
		if err := conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(pingTimeout)); err != nil {
			failCount++
			log.Printf("[Heartbeat] Device %s ping failed (%d/%d): %v", deviceId, failCount, maxFails, err)

			if failCount >= maxFails {
				log.Printf("[Heartbeat] Device %s is offline", deviceId)
				m.RemoveDevice(deviceId)
				return
			}
			// 指数退避重试
			backoff := time.Duration(1<<uint(failCount-1)) * time.Second
			if backoff > time.Second*10 {
				backoff = time.Second * 10
			}
			time.Sleep(backoff)
		} else {
			failCount = 0
			onlineCache.Store(deviceId, true)
			lastCheckTime.Store(deviceId, time.Now())
			conn.SetReadDeadline(time.Now().Add(time.Minute * 5))
		}
	}
}

func NewDeviceService(db *sql.DB) *DeviceService {
	return &DeviceService{db: db}
}

// 验证机器码
func (s *DeviceService) ValidateRobotID(ctx context.Context, robotID string) (*RobotConfig, error) {
	// 1. 检查机器码是否存在且有效
	var config RobotConfig
	err := s.db.QueryRowContext(ctx, `
		SELECT r.robot_id, r.status, r.expire_time, 
			   c.qa_type, c.callback_url, c.reply_all, 
			   c.robot_key_check, c.encrypt_type
		FROM wqyf_robot_codes r
		LEFT JOIN wqyf_robot_configs c ON r.robot_id = c.robot_id
		WHERE r.robot_id = ?
	`, robotID).Scan(
		&config.RobotID,
		&config.Status,
		&config.ExpireTime,
		&config.QAType,
		&config.CallbackURL,
		&config.ReplyAll,
		&config.RobotKeyCheck,
		&config.EncryptType,
	)

	if err == sql.ErrNoRows {
		return nil, errors.New("robot ID not found")
	}
	if err != nil {
		return nil, err
	}

	// 2. 检查状态
	if config.Status != 1 {
		return nil, errors.New("robot ID is disabled")
	}

	// 3. 检查是否过期
	if !config.ExpireTime.IsZero() && config.ExpireTime.Before(time.Now()) {
		return nil, errors.New("robot ID has expired")
	}

	return &config, nil
}

// 更新机器人配置
func (s *DeviceService) UpdateRobotConfig(ctx context.Context, config *RobotConfig) error {
	_, err := s.db.ExecContext(ctx, `
		INSERT INTO wqyf_robot_configs (
			robot_id, qa_type, callback_url, reply_all, 
			robot_key_check, encrypt_type
		) VALUES (?, ?, ?, ?, ?, ?)
		ON DUPLICATE KEY UPDATE
			qa_type = VALUES(qa_type),
			callback_url = VALUES(callback_url),
			reply_all = VALUES(reply_all),
			robot_key_check = VALUES(robot_key_check),
			encrypt_type = VALUES(encrypt_type)
	`,
		config.RobotID,
		config.QAType,
		config.CallbackURL,
		config.ReplyAll,
		config.RobotKeyCheck,
		config.EncryptType,
	)

	return err
}

// 获取机器人配置
func (s *DeviceService) GetRobotConfig(ctx context.Context, robotID string) (*RobotConfig, error) {
	config := &RobotConfig{}
	err := s.db.QueryRowContext(ctx, `
		SELECT robot_id, qa_type, callback_url, reply_all, 
			   robot_key_check, encrypt_type
		FROM wqyf_robot_configs
		WHERE robot_id = ?
	`, robotID).Scan(
		&config.RobotID,
		&config.QAType,
		&config.CallbackURL,
		&config.ReplyAll,
		&config.RobotKeyCheck,
		&config.EncryptType,
	)

	if err == sql.ErrNoRows {
		return nil, errors.New("robot config not found")
	}
	if err != nil {
		return nil, err
	}

	return config, nil
}
